﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FunctionImage2D
{
    class Program
    {
        private static int N = 1024;
       
        private static double Cost(double k, int nLeft, int nRight, double pLeft, double pRight)
        {
            return pLeft * Math.Pow(nLeft, k) + pRight * Math.Pow(nRight, k);
        }
       
        private static double EvaluateFunction(double x, double y)
        {
            double d = y * 0.1f;
            double k = x;
            double length = 0.707 + N * d;
            double cost1 = EvalCostAtSplit(k, d, length, 1);
            double cost2 = EvalCostAtSplit(k, d, length, N / 2);
            return cost2/cost1;
        }

        private static double EvalCostAtSplit(double k, double d, double length, int pos)
        {
            double xLeft = (pos - 1) * d + 0.707;
            double xRight = length - (pos * d);
            double pLeft = 4 * xLeft + 2.0;
            double pRight = 4 * xRight + 2.0;
            return Cost(k, pos, N - pos, pLeft, pRight);
        }

        static void Main(string[] args)
        {
            Color minColor = Color.FromArgb(0, 255, 0);
            Color maxColor = Color.Red;
            float minValue = 0.0f;
            float maxValue = 1.0f;
            const int size = 1024;
            using (Bitmap bmp = new Bitmap(size, size))
            {
                var data = bmp.LockBits(new Rectangle(0, 0, size, size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
                unsafe
                {
                    int* ptr = (int*)data.Scan0;
                    for (int y = 0; y < size; y++)
                    {
                        for (int x = 0; x < size; x++)
                        {
                            int* pixel = ptr + y * size + x;
                            double value = EvaluateFunction((double)x / size, (double)y / size);
                            double t = (value - minValue) / (maxValue - minValue);
                            t = t * t;
                            if (t > 1.0f) t = 1.0f;
                            double invT = 1.0f - t;
                            var color = Color.FromArgb((int)(minColor.R * invT + maxColor.R * t),
                                (int)(minColor.G * invT + maxColor.G * t),
                                (int)(minColor.B * invT + maxColor.B * t));
                            if (value > 0.999)
                                color = Color.Yellow;
                            *pixel = color.ToArgb();
                        }
                    }
                }
                bmp.UnlockBits(data);
                bmp.Save("result.bmp");
            }
        }    
    }
}
